package com.infopatent.shldevtools.tools;

import com.jacob.activeX.*;
import com.jacob.com.*;

/**
 * <pre>使用jacob实现以下功能： 写word文件； 调用word文件中的宏； word文档转换为PDF文件的功能。
 *
 * 注意——使用的环境条件： 
 * 1.Word2003、Adobe Acrobat 7.0.5 Professional(由7.0版在线升级获得，因为7.0版存在bug)； 
 * 2.并且关闭了Adobe PDF打印机属性->Adobe PDF Setting中的“do not send fonts to PDF”选项； 
 * 3.设置了Adobe PDF打印机属性->常规->打印首选项->布局->高级->文档选项->postscript options->TrueType font download
 * option为Native TrueType。 
 * 第3个条件是可选的，第1、2个条件是必须的。不然会可能出现错误。
 *
 * 参考资源： 
 * Create PDF files from Microsoft Excel using Acrobat (6.0 and 7.0 on Windows)： 
 * http://www.adobe.com/support/techdocs/328398.html Article-Word Doc to PDF Conversion
 * http://www.suodenjoki.dk/us/productions/articles/word2pdf.htm
 * 微软的javasdk文档和adobe的Distiller api文档（在项目的dependencies目录中）
 * </pre>
 * 
 * @author shaohailong
 */

public class DispatchMSWordTools {

    private ActiveXComponent wordCom = null;
    private Dispatch wordDoc = null;
    private final Variant False = new Variant(false);
    private final Variant True = new Variant(true);

    /**
     * 打开word文档
     *
     * @param filePath word文档
     * @return 返回word文档对象
     */
    public boolean openWord(String filePath) {
        //建立ActiveX部件
        wordCom = new ActiveXComponent("Word.Application");

        try {
            //返回wrdCom.Documents的Dispatch
            Dispatch wrdDocs = wordCom.getProperty("Documents").toDispatch();
            //调用wrdCom.Documents.Open方法打开指定的word文档，返回wordDoc
            wordDoc = Dispatch.invoke(wrdDocs, "Open", Dispatch.Method, new Object[]{filePath}, new int[1]).toDispatch();
            return true;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return false;
    }

    /**
     * 关闭word文档
     */
    public void closeWord() {
        //关闭word文件
        wordCom.invoke("Quit", new Variant[]{});
        ComThread.Release();
    }

    /**
     * 打开word，调用word中的宏
     *
     * @param filePath word文件路径
     * @param macroName 被调用的宏名字
     * @param parameter 调用宏的参数数组
     */
    public void callWordMacro(String filePath, String macroName, Object parameter[]) {

        if (!openWord(filePath)) {
            closeWord();
            return;
        } else {
            //使用方法传入的参数parameter调用word文档中的MyWordMacro宏
            Dispatch.invoke(wordDoc, macroName, Dispatch.Method, parameter, new int[1]);
            closeWord();
        }
    }

    /**
     * 打开word，替换其中的文字
     *
     * @param filePath word文件路径
     * @param sourceStr 源文字
     * @param replaceStr 替换后的文字
     */
    public void callReplaceWord(String filePath, String sourceStr, String replaceStr) {

        if (!openWord(filePath)) {
            closeWord();
            return;
        }

        try {
            //获得Selection对象
            Dispatch selectDoc = wordCom.getProperty("Selection").toDispatch();
            //获得Find对象
            Dispatch find = Dispatch.call(selectDoc, "Find").toDispatch();

            //设置替换的方法属性，但是不支持ReplaceWith的属性，而且使用Replancement.Text属性也无济于事。
            Dispatch.put(find, "Text", sourceStr);

            //所以使用Find对象的Execute(FindText, MatchCase, MatchWholeWord, MatchWildcards, MatchSoundsLike, MatchAllWordForms, Forward, Wrap, Format, ReplaceWith, Replace, MatchKashida, MatchDiacritics, MatchAlefHamza, MatchControl)方法
            //详细内容见MSDN的office2000开发文档
            Variant True = new Variant(true);
            Variant False = new Variant(false);
            Variant FindText = new Variant(sourceStr);
            Variant ReplaceWith = new Variant(replaceStr);
            Variant Format = False;
            Variant Forward = True;
            Variant MatchCase = True;
            Variant MatchWholeWord = True;
            Variant MatchWildcards = False;
            Variant MatchSoundsLike = False;
            Variant MatchAllWordForms = False;
            int wdFindWrap_FindContinue = 1;
            Variant Wrap = new Variant(wdFindWrap_FindContinue);
            int wdReplace_ReplaceAll = 2;
            Variant Replace = new Variant(wdReplace_ReplaceAll);

            //使用callN方法调用execute方法
            Dispatch.callN(find, "Execute", (Object[]) new Variant[]{
                        FindText, MatchCase, MatchWholeWord, MatchWildcards,
                        MatchSoundsLike, MatchAllWordForms, Forward, Wrap,
                        Format, ReplaceWith, Replace
                    });
            Dispatch.invoke(wordDoc, "SaveAs", Dispatch.Method, new Object[]{"c:\\111.doc"}, new int[1]);
            closeWord();
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            closeWord();
        }
    }

    /**
     * 将word文档打印为PS文件后，使用Distiller将PS文件转换为PDF文件
     *
     * @param sourceFilePath 源文件路径
     * @param destinPSFilePath 首先生成的PS文件路径
     * @param destinPDFFilePath 生成PDF文件路径
     */
    public void docToPDF(String sourceFilePath, String destinPSFilePath, String destinPDFFilePath) {
        if (!openWord(sourceFilePath)) {
            closeWord();
            return;
        }
        //建立Adobe Distiller的com对象
        ActiveXComponent distiller = new ActiveXComponent("PDFDistiller.PDFDistiller.1");
        try {
            //设置当前使用的打印机，我的Adobe Distiller打印机名字为"Adobe PDF"
            wordCom.setProperty("ActivePrinter", new Variant("Adobe PDF"));

            //设置printout的参数，将word文档打印为postscript文档。目前只使用了前5个参数，如果要使用更多的话可以参考MSDN的office开发相关api
            //是否在后台运行
            Variant Background = False;
            //是否追加打印
            Variant Append = False;
            //打印所有文档
            int wdPrintAllDocument = 100;
            Variant Range = new Variant(wdPrintAllDocument);
            //输出的postscript文件的路径
            Variant OutputFileName = new Variant(destinPSFilePath);
//                Variant From =new Variant(1);
//                Variant To  =new Variant(1);
//                int wdPrintDocumentContent=2;
//                Variant Item  =new Variant(wdPrintDocumentContent);
//                Variant Copies =new Variant(1);
//                Variant Pages =new Variant();
//                int wdPrintAllPages=0;
//                Variant PageType =new Variant(wdPrintAllPages);
//                Variant PrintToFile =True;
//                Variant Collate =True;
//                Variant FileName =new Variant(sourceFilePath);
//                Variant ActivePrinterMacGX =new Variant();
//                Variant ManualDuplexPrint =False;
//                Variant PrintZoomColumn =new Variant();
//                Variant PrintZoomRow  =new Variant();
//                Variant PrintZoomPaperWidth =new Variant();
//                Variant PrintZoomPaperHeight =new Variant();
//        
//                Variant[] args=new Variant[]{Background,Append,Range,OutputFileName,From,To,Item,Copies,Pages,PageType,
//                                    PrintToFile,Collate,FileName,ActivePrinterMacGX,ManualDuplexPrint,PrintZoomColumn,PrintZoomRow,
//                                    PrintZoomPaperWidth,PrintZoomPaperHeight};

            //调用word文档对象的PrintOut方法：将word文档打印为postscript文档，简称ps文档
            Dispatch.callN(wordDoc, "PrintOut", (Object[]) new Variant[]{Background, Append, Range, OutputFileName});
            System.out.println("由word文档打印为ps文档成功！");

            
            //调用Distiller对象的FileToPDF方法所用的参数，详细内容参考Distiller Api手册
            //作为输入的ps文档路径
            Variant inputPostScriptFilePath = new Variant(destinPSFilePath);
            //作为输出的pdf文档的路径
            Variant outputPDFFilePath = new Variant(destinPDFFilePath);
            //定义FileToPDF方法要使用adobe pdf设置文件的路径，在这里没有赋值表示并不使用pdf配置文件
            Variant PDFOption = new Variant("");
            //调用FileToPDF方法将ps文档转换为pdf文档
            Dispatch.callN(distiller, "FileToPDF", (Object[]) new Variant[]{inputPostScriptFilePath, outputPDFFilePath, PDFOption});
//            Runtime.getRuntime().exec(destinPSFilePath);
            System.out.println("由ps文档转换为pdf文档成功！");
//            distiller.invoke("exit", PDFOption);
            
            
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            closeWord();
        }
    }

    /**
     * 测试使用的方法,确保方法,以及环境没有问题,开发时使用.
     * @param argv 
     */
    public static void main(String[] argv) {
        DispatchMSWordTools d = new DispatchMSWordTools();
//                d.callWordMacro("E:/eclipse3.1RC3/workspace/jacobPractice/src/com/bjinfotech/practice/jacob/MacroTest.doc","MyWordMacro",new String[]{"这是调用word宏的测试程序"});
//                d.callReplaceWord("E:/eclipse3.1RC3/workspace/jacobPractice/src/com/bjinfotech/practice/jacob/MacroTest.doc","$TITLE$","文字已经被替换");
        d.docToPDF("C:\\Users\\Administrator\\Desktop\\130447HF-TW-递交稿.DOC", "c:/1p.ps", "c:/1p.pdf");
    }
}
